/*!
 * GwAdmin Development v1.2.0
 * (c) 2018-2019 Gwzh
 * build in: 2019-4-18 16:21:44
 */

'use strict';

var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? function(obj) { return typeof obj } : function(obj) { return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj };

/*!
 entity.js
 */
layui.define(['validate', 'helper'], function(e) {
  var $ = layui.jquery;
  var form = layui.form;
  var validate = layui.validate;

  var Props = { form: 'data-form', field: 'data-field', choose: 'data-choose' };
  var debug = layui.hint();

  // 检测 jQuery 对象的唯一性
  var checkJqueryObject = function checkJqueryObject($selector) {
    var length = $selector.length;
    var flag = true;
    if (length !== 1) {
      debug.error('[checkJqueryObject] 必须指定唯一容器');
      flag = false;
    }
    return flag;
  };
  // 检测数据的格式和值
  var checkData = function checkData(data) {
    var _type = typeof data === 'undefined' ? 'undefined' : _typeof(data);
    var flag = true;
    if (!data) {
      debug.error('[checkData] 数据不可为空');
      flag = false;
    } else if (_type === 'undefined') {
      debug.error('[checkData] 数据格式应为json格式');
      flag = false;
    }
    return flag;
  };
  // 转化数据的值使之成为 Object
  var getObjectData = function getObjectData(data) {
    var _type = typeof data === 'undefined' ? 'undefined' : _typeof(data);
    var result = {};
    if (data) {
      result = _type === 'string' ? JSON.parse(data) : _type === 'object' ? JSON.parse(JSON.stringify(data)) : {};
    }
    return result;
  };
  var entity = {
    /**
     * @function 设置form中的值
     * @param {object} selector JQ选择器
     * @param {object | string} data Json格式数据
     * @param {boolean} isWritable 是否可重新赋值
     */
    set: function set(selector, data, isWritable) {
      var $form = $(selector);
      if (!checkJqueryObject($form)) {
        return false;
      }
      var formValue = $form.attr(Props.form);
      var formEntity = getObjectData(data);
      if (!checkData(formEntity)) {
        return false;
      }
      formEntity = formEntity[formValue] ? formEntity[formValue] : formEntity;
      $form.find('[' + Props.field + ']').each(function(index, item) {
        var field = $(item).attr(Props.field);
        var fieldNames = field.split('.');
        var value = formEntity;
        for (var _index = 0; _index < fieldNames.length; _index++) {
          value = value[fieldNames[_index]];
          if (!value) {
            break;
          }
        }
        if ($(this).attr(Props.choose)) {
          var tempValue = [];
          if (!value) return;
          if ($.isArray(value)) {
            tempValue = value;
          } else {
            tempValue.push(value);
          }
          var chooses = $(this).find('input[type=' + $(this).attr(Props.choose) + ']');
          var tempArrayString = [];
          $.each(tempValue, function(index, item) {
            tempArrayString.push(item.toString());
          });
          chooses.each(function(index, item) {
            if ($.inArray(item.value.toString(), tempArrayString) !== -1) {
              item.checked = true;
            } else {
              item.checked = false;
            }
          });
        } else {
          if ($(this).attr('type') === 'checkbox' || $(this).attr('type') === 'radio') {
            $(this).attr('checked', Boolean(value));
          } else {
            var tagName = this.tagName;
            tagName = tagName.toLowerCase();
            if (tagName === 'input' || tagName === 'select' || tagName === 'textarea') {
              $(this).attr('defaultValue', value);
              if (value) {
                $(this).val(value);
              } else {
                // typeof value === 'number' ? $(this).val(0) : $(this).val('');
                if (typeof value === 'number') {
                  $(this).val(0);
                }
              }
            } else {
              if (value) {
                $(this).attr('defaultValue', value);
                if ($(this).html() !== '' && !isWritable) {
                  var tmp = $(this).data('field');
                  var elStr = '<' + tagName + ' data-field="' + tmp + '"></' + tagName + '>';
                  debug.error('标签[ ' + elStr + ' ] 存在值或者其他标签，无法填入新值');
                } else {
                  $(this).html(value);
                }
              } else {
                // typeof value === 'number' ? $(this).html(0) : $(this).html('');
                if (typeof value === 'number') {
                  $(this).html(0); // @hezl 2018/5/28 修改了非表单使用html赋值
                }
              }
            }
          }
        }
      });
      form.render();
    },

    /**
     * @function 获取form中的值，使用在自己的form指定一个
     * data-form 即<form data-form="demo"></form>
     * 每一个你需要的表单可以写入<input type="checkbox" data-field="sex">
     * 那么返回将会是{demo:{sex:0}}
     * 如果不指定data-form，那么返回结果是{sex:0}
     * @param selector 【jquery选择器, '#id', '.className', '[attrs]' ...】
     * @param call （如果写入方法，那么将会将返回值返回给方法）
     * @return {{}}
     */
    get: function get(selector, call) {
      var _this = this;

      var result = {}; // 返回的最终结果
      var $form = $(selector);
      if (!checkJqueryObject($form)) {
        return false;
      }
      var formValue = $form.attr(Props.form);
      formValue && (result[formValue] = {});

      // 2018-04-27 表单验证
      if (!this.check(selector)) {
        return false;
      }
      var setObject = function setObject(list, value, result) {
        if (list.length === 0) return;
        if (list.length > 1) {
          for (var i = 0; i < list.length - 1; i++) {
            if (result[list[i]] == undefined) {
              result[list[i]] = {};
            }
            result = result[list[i]];
          }
          result[list[list.length - 1]] = value;
        } else {
          list[0] && (result[list[0]] = value);
        }
      };
      var $fields = $form.find('[' + Props.field + ']');
      $fields.each(function(_, field) {
        var fieldChoose = field.getAttribute('' + Props.choose);
        var fieldTagName = field.tagName.toLowerCase(); // 获取组件所在元素的标签名称
        var fieldType = field.type || field.getAttribute('type');
        var fieldValue = null;
        var fieldKeys = []; // data-field 支持以object.object的形式，所以这里需要处理
        if (field.getAttribute('' + Props.field)) {
          fieldKeys = field.getAttribute('' + Props.field).split('.');
        }
        if (fieldChoose) {
          var _ret = [];
          var chooses = field.querySelectorAll('input[type=' + fieldChoose + ']');
          for (var j = 0; j < chooses.length; j++) {
            var choose = chooses[j];
            choose.checked && _ret.push(choose.value || '');
          }
          fieldValue = _ret.join(',');
        } else {
          if (fieldType === 'checkbox' || fieldType === 'radio') {
            fieldValue = field.checked;
          } else {
            if (fieldTagName === 'td' || fieldTagName === 'span' || fieldTagName === 'div' || fieldTagName === 'label') {
              fieldValue = field.innerText;
            } else {
              fieldValue = field.value || '';
            }
          }
        }
        var optionArray = [fieldKeys, fieldValue, result];
        formValue && (optionArray[2] = result[formValue]);
        setObject.apply(_this, optionArray);
      });

      if (typeof call === 'function') {
        call(result);
      } else {
        return result;
      }
    },

    /**
     * 检测表单的填写规范性 2018/04/27
     * @param form
     * @param option
     * @return {boolean}
     */
    check: function check(form, option) {
      // 设置默认返回值
      var result = true;
      // 处理入参
      // 搜索指定的form，未找到报错且终止程序
      var selector = document && document.querySelector(form);
      if (!selector) {
        debug.error('[check] 必须指定唯一容器');
        return false;
      }
      // 判断option类型，是配置还是方法，用临时变量接受
      var _methods = {};
      var _target = [];
      var _callback = function _callback() {};
      var optionType = typeof option === 'undefined' ? 'undefined' : _typeof(option);

      if (optionType === 'function') {
        _callback = option;
      } else if (optionType === 'object') {
        option.methods && (_methods = option.methods);
        option.target && (_target = option.target); // TODO
        option.callback && (_callback = option.callback);
      }

      // 样式的配置和处理
      var css = {
        CONST: 'layui-form-danger',
        set  : function set() {
          var symbol = this.CONST;
          if (document.querySelector('.' + symbol)) return;
          // 组装样式
          var node = document.createElement('style');
          var text = '.' + symbol + ', .' + symbol + ' + .layui-form-select { outline: 2px dashed #FF5722 }';
          node.id = symbol;
          node.type = 'text/css';
          node.innerHTML = text;
          $('head').append($(node));
        },
        add: function add(field) {
          if (!field) return false;
          field.focus();
          $(field).addClass(this.CONST);
        },
        remove: function remove(field) {
          if (!field) return false;
          $(field).removeClass(this.CONST);
        }
      };

      $.extend(true, validate, _methods);

      var idx = _target.length;
      var timer = new Date().getTime();
      while (idx > 0) {
        var item = _target[idx - 1];
        var el = item.el || '';
        var queryField = selector.querySelector(el);

        queryField && queryField.setAttribute('data-msg-' + timer, idx);
        idx--;
      }

      var fields = []; // 存放表单下带有data-verify的组件
      // 寻找指定的控件
      fields.unshift.apply(fields, selector.querySelectorAll('[data-verify]'));

      // css.set()
      $('[type="reset"]').on('click', function(e) {
        $('.' + css.CONST).removeClass(css.CONST);
      });
      // 循环去除每一个需要验证的表单的danger样式
      for (var i = 0, len = fields.length; i < len; i++) {
        var field = fields[i];
        css.remove(field);
      }

      var isContinue = true; // 控制循环的开关
      // 检测控件的值正确性，遇到错误停止后面的检测，直接给出返回结果
      for (var i = 0, len = fields.length; i < len; i++) {
        if (!isContinue) break;

        var field = fields[i];
        var fieldTagName = field.tagName.toLowerCase(); // 获取组件所在元素的标签名称

        // 判断符合规则的控件
        var fieldChoose = field.getAttribute('data-choose');
        var hasChoose = !!fieldChoose; // radio和checkbox组也检测
        var canInput = hasChoose || fieldTagName === 'input' || fieldTagName === 'select' || fieldTagName === 'textarea';

        if (canInput) {
          // 获取控件的验证属性
          var dataVerify = (field.getAttribute('data-verify') || '').trimAll();
          // 切割验证的属性
          var vers = dataVerify.split('|');
          var hasRequired = function hasRequired() {
            for (var _i = 0, _len = vers.length; _i < _len; _i++) {
              if (vers[_i] === 'required') {
                return true;
              }
            }
            return false;
          };
          // @hezl 2018/5/8 去除默认的required
          // if (!hasRequired()) vers.unshift('required')

          // 获取当前控件的值
          var currentValue = hasChoose ? (function() {
            var tempValue = [];
            var chooses = field.querySelectorAll('input[type=' + fieldChoose + ']');
            for (var j = 0, jLen = chooses.length; j < jLen; j++) {
              var choose = chooses[j];
              choose.checked && tempValue.push(choose.value || '');
            }
            return tempValue.join(',');
          }()) : field.value;
          // 是否自定义当前输入框的判断
          var dataMsg = field.getAttribute('data-msg-' + timer) || 0;

          var optionField = +dataMsg > 0 && _target[dataMsg - 1];
          // 循环处理验证的条件（遇到错误则停止）
          for (var k = 0, kLen = vers.length; k < kLen; k++) {
            // 去除字符串中的空白
            var nowCheck = (vers[k] + '').trimAll();
            // 开始处理
            var tempArray = nowCheck.split(':');
            var tempLen = tempArray.length;
            var verKey = (tempArray[0] + '').trim(); // 验证的属性key
            var verArg = tempLen >= 2 && (tempArray[1] + '').trim(); // 验证的属性value

            // 处理入参
            var args = eval(verArg) ? eval(verArg) : '';

            Array.isArray(args) ? args.unshift(currentValue) : args = [currentValue, args];

            var errText = '';
            var isFn = typeof validate[verKey] === 'function';

            var isTrue = false; // 是否命中
            if (validate[verKey]) {
              // @hezl 2018/5/22 除了required，minLen, maxLen 其他的不验证非空
              if (verKey === 'required' || verKey === 'minLen' || verKey === 'maxLen') {
                isTrue = isFn ? errText = validate[verKey].apply(this, args) : !validate[verKey][0].test(currentValue);
              } else {
                currentValue += ''; // 将值转成string
                if (currentValue !== '') {
                  isTrue = isFn ? errText = validate[verKey].apply(this, args) : !validate[verKey][0].test(currentValue);
                }
              }
              errText = errText || validate[verKey][1];
            }

            if (optionField) {
              var __type = _typeof(optionField.msg);

              if (__type === 'function') {
                errText = optionField.msg(this, args);
              } else {
                errText = optionField.msg;
              }
            }

            if (isTrue) {
              isContinue = false;
              css.add(field);
              layer ? layer.msg(errText) : alert && alert(errText);
              result = !isTrue;
              break; // 遇到错误中止
            } else {
              css.remove(field);
            }
          }
        } else {
          css.remove(field);
        }
      }

      return result;
    }
  };
  e('entity', entity);
});
